package ar.com.larreta.colegio.entidades;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;

import ar.com.larreta.entidades.Persona;

@Entity
@Table(name = "alumno")
// Solamente trae los que no fueron borrados logicamente
@Where(clause="fechaEliminacion IS NULL")
//Borrado logico
@SQLDelete (sql="UPDATE Persona SET fechaEliminacion=CURRENT_TIMESTAMP WHERE ID=?")
public class Alumno extends Persona {

	private Nivel nivel;
	private Anio anio;
	private Division division;
	private Responsable responsable;
	private Set<PlanDePago> planesDePagos;
	private Set<UnidadDePago> unidadesDePago;
	
	private List<Obligacion> obligacionesPendientes = null;
	private List pagos = null;
	
	@Transient
	public Collection getObligaciones() {
		if (obligacionesPendientes==null){
			obligacionesPendientes = new ArrayList<Obligacion>();
			
			Map<Long, Double> pagosSumarizados = getPagosSumarizados();
			
			Set<PlanDePago> planes = getPlanesDePagos();
			if (planes!=null){
			Iterator<PlanDePago> iPlanes = planes.iterator();
				while (iPlanes.hasNext()) {
					PlanDePago planDePago = (PlanDePago) iPlanes.next();
					Set<Obligacion> obligaciones = planDePago.getObligaciones();
					if (obligaciones!=null){
						Iterator<Obligacion> iObligaciones = obligaciones.iterator();
						while (iObligaciones.hasNext()) {
							Obligacion obligacion = (Obligacion) iObligaciones.next();
							if ((pagosSumarizados.get(obligacion.getId())==null) ||  
									(obligacion.getValor()>pagosSumarizados.get(obligacion.getId()))){
								obligacion.setPagado(pagosSumarizados.get(obligacion.getId()));
								obligacionesPendientes.add(obligacion);
							}
						}
					}
				}
			}
			
			Collections.sort(obligacionesPendientes);
		}
		
		return obligacionesPendientes;
	}
	
	public void setObligacion(Collection obligaciones){}

	@Transient
	public Double getTotalAdeudado(){
		Date actual = new Date();
		Double total = new Double(0);
		Collection obligaciones = getObligaciones();
		if (obligaciones!=null){
			Iterator it = obligaciones.iterator();
			while (it.hasNext()){
				Obligacion obligacion = (Obligacion) it.next();
				if (obligacion.getVencimiento().before(actual)){
					total+=obligacion.getAdeudado();
				}
			}
		}
		return total;
	}
	
	public void setTotalAdeudado(Double total){}
	
	@Transient
	public String getProximaObligacionImpaga(){
		String proxima = "";
		Collection obligaciones = getObligaciones();
		if (obligaciones!=null){
			Iterator it = obligaciones.iterator();
			if (it.hasNext()){
				Obligacion obligacion = (Obligacion) it.next();
				proxima = obligacion.getNombre();
			}
		}
		return proxima;
	}
	
	public void setProximaObligacionImpaga(String proxima){}

	@Transient
	public String getSiguienteObligacionImpaga(){
		String siguiente = "";
		Collection obligaciones = getObligaciones();
		if (obligaciones!=null){
			Iterator it = obligaciones.iterator();
			if (it.hasNext()){
				it.next();
				if (it.hasNext()){
					Obligacion obligacion = (Obligacion) it.next();
					siguiente = obligacion.getNombre();
				}
			}
		}
		return siguiente;
	}
	
	public void setSiguienteObligacionImpaga(String siguiente){}
	
	@Transient
	private Map<Long, Double> getPagosSumarizados() {
		Map<Long, Double> pagosSumarizados = new HashMap<Long, Double>();
		Set<UnidadDePago> unidades = getUnidadesDePago();
		if (unidades!=null){
			Iterator<UnidadDePago> iUnidades = unidades.iterator();
			while (iUnidades.hasNext()) {
				UnidadDePago unidadDePago = (UnidadDePago) iUnidades.next();
				if (unidadDePago.getProducto() instanceof Obligacion) {
					Obligacion obligacion = (Obligacion) unidadDePago.getProducto();
					Double actual = pagosSumarizados.get(obligacion.getId());
					if (actual==null){
						actual=new Double(0);
					}
					actual += unidadDePago.getValor();
					pagosSumarizados.put(obligacion.getId(), actual);				
				}
			}
		}
		return pagosSumarizados;
	}
	
	
	@OneToMany (mappedBy="alumno", fetch= FetchType.LAZY)
	public Set<UnidadDePago> getUnidadesDePago() {
		return unidadesDePago;
	}
	public void setUnidadesDePago(Set<UnidadDePago> unidadesDePago) {
		this.unidadesDePago = unidadesDePago;
	}
	
	@ManyToOne (fetch=FetchType.LAZY)
	@JoinColumn (name="idResponsable")	
	public Responsable getResponsable() {
		return responsable;
	}
	public void setResponsable(Responsable responsable) {
		this.responsable = responsable;
	}
	
	@ManyToMany
	@JoinTable(name = "alumno_plan", joinColumns = { @JoinColumn(name = "idAlumno") }, inverseJoinColumns = { @JoinColumn(name = "idPlan") })
	public Set<PlanDePago> getPlanesDePagos() {
		if (planesDePagos==null){
			planesDePagos = new HashSet<PlanDePago>();
		}
		return planesDePagos;
	}
	public void setPlanesDePagos(Set<PlanDePago> planesDePagos) {
		this.planesDePagos = planesDePagos;
	}
	
	@ManyToOne (fetch=FetchType.LAZY)
	@JoinColumn (name="idNivel")	
	public Nivel getNivel() {
		return nivel;
	}
	public void setNivel(Nivel nivel) {
		this.nivel = nivel;
	}
	
	@ManyToOne (fetch=FetchType.LAZY)
	@JoinColumn (name="idAnio")	
	public Anio getAnio() {
		return anio;
	}
	public void setAnio(Anio anio) {
		this.anio = anio;
	}
	
	@ManyToOne (fetch=FetchType.LAZY)
	@JoinColumn (name="idDivision")	
	public Division getDivision() {
		return division;
	}
	public void setDivision(Division division) {
		this.division = division;
	}
	
	@Override
	public boolean equals(Object obj) {
		try{
			Alumno alumno = (Alumno) obj;
			return this.getId().equals(alumno.getId());
		} catch (Exception e){}
		return Boolean.FALSE;
	}

	@Transient
	public Collection getPagos() {
		if (pagos==null){
			pagos = new ArrayList<Pago>();
			
			Set unidades = getUnidadesDePago();
			if (unidades!=null){
				Iterator iUnidades = unidades.iterator();
				while (iUnidades.hasNext()) {
					UnidadDePago unidad = (UnidadDePago) iUnidades.next();
					pagos.add(unidad.getPago());				
				}
			}
			
			Collections.sort(pagos);
		}
		return pagos;
	}
	
	public void setPagos(Collection pagos){}
	
	@Transient
	public String getUltimoPagoRealizado(){
		String ultimo = "";
		Collection pagos = getPagos();
		if (pagos!=null){
			Iterator it = pagos.iterator();
			if (it.hasNext()){
				Pago pago = (Pago) it.next();
				ultimo = pago.getProducto().getNombre();
			}
		}
		return ultimo;
	}
	
	public void setUltimoPagoRealizado(String pago){}

	@Transient
	public String getAnteriorPagoRealizado(){
		String anterior = "";
		Collection pagos = getPagos();
		if (pagos!=null){
			Iterator it = pagos.iterator();
			if (it.hasNext()){
				it.next();
				if (it.hasNext()){
					Pago pago = (Pago) it.next();
					anterior = pago.getProducto().getNombre();
				}
			}
		}
		return anterior;
	}
	
	public void setAnteriorPagoRealizado(String pago){}
	
}
